Uncreative Labs Logo

How to use ASM code in Qbasic


BACK

For this page to be of much use to you, you should be able to program in Basic!
First things first, if you want to use ASM code in Qbasic, then you will need the following tools:
I will be describing how to use a Mouse in qbasic. This is because it is a fairly simple task to accomplish in asm, yet very difficult just using QB. The process is split into three main stages:
  1. Writing and assembling the asm code
  2. Creating the QuickBasic Library
  3. Writing the qb code

1)Writing the ASM code

If you already know *any* asm, then you might as well skip to the end of this section. This ASM code is going to have to provide five procedures for Qbasic; turn the mouse pointer on, off, read X and Y position, and read the status of the buttons. For the first procedure, turn the pointer on, we have to find the necessary interrupt. This can be found by looking at Ralf Brown's interrupt list (you really should download this... see links at the bottom of the page). This list contains all of (or at least nearly all of) the interrupts for IBM PC/AT's and compatibles. But the one's we need are the ones used to communicate with the mouse driver, the following gives details of the interrupts needed to use the mouse (copied from Ralf Brown's interrupt list):
--------M-330001------------------------------
INT 33 - MS MOUSE v1.0+ - SHOW MOUSE CURSOR
	AX = 0001h
SeeAlso: AX=0002h,INT 16/AX=FFFEh,INT 62/AX=007Bh,INT 6F/AH=06h"F_TRACK_ON"
--------M-330002------------------------------
INT 33 - MS MOUSE v1.0+ - HIDE MOUSE CURSOR
	AX = 0002h
Note:	multiple calls to hide the cursor will require multiple calls to
	  function 01h to unhide it.
SeeAlso: AX=0001h,AX=0010h,INT 16/AX=FFFFh,INT 62/AX=007Bh
SeeAlso: INT 6F/AH=08h"F_TRACK_OFF"
--------M-330003------------------------------
INT 33 - MS MOUSE v1.0+ - RETURN POSITION AND BUTTON STATUS
	AX = 0003h
Return: BX = button status (see #03168)
	CX = column
	DX = row
Note:	in text modes, all coordinates are specified as multiples of the cell
	  size, typically 8x8 pixels
SeeAlso: AX=0004h,AX=000Bh,INT 2F/AX=D000h"ZWmous"

Bitfields for mouse button status:
Bit(s)	Description	(Table 03168)
 0	left button pressed if 1
 1	right button pressed if 1
 2	middle button pressed if 1 (Mouse Systems/Logitech/Genius)
So, for the first procedure we need, turn mouse pointer on, we need to use interrupt 33h sub function 0001h. This means the mouse pointer can be turned on by three lines of ASM code:
mov	ax, 0001h
int	33h
ret
The first line stores the function we want to use in the CPU's ax (accumulator) register. The second generates an interrupt 33h, this basically means in this case that a block of the mouse driver code will be ran, and the last line will return control back to qb. To turn the mouse pointer off is almost the same, you just use 0002h instead of 0001h. The next procedure required is used to read the status of the mouse. I'll be using 3 different procedures for this, one to read the X co-ordinate, one for Y and another for the buttons. I'm sure its possible to do this all on one procedure, and do a little extra processing in QB, but i like to keep things simple. The X Co-ordinate of the mouse can be read using this asm code:
mov	ax, 0003h
int	33h
mov	ax, dx
ret
As before, the first two line select and call the required function in the mouse driver. After the interrupt, the X co-ordinate of the mouse will be stored in dx (data register), the Y in cx (count register), and the states of the buttons in bx (Base register). The value retuned to QB has to be stored in ax, so the third line copies the X coordinate to the ax register. The procedure to read the Y co-ordinate will be the same, except it will use mov ax, cx instead of mov ax, dx; and the procedure to use the buttons will use mov ax, bx. This can all be put together into one asm source file, QBMouse.asm:
.MODEL MEDIUM, BASIC
.stack
.data
.code

PUBLIC MousePointerOn
MousePointerOn PROC
mov 	ax,0001h
int 	33h
ret
MousePointerOn ENDP


PUBLIC MousePointerOff
MousePointerOff PROC
mov 	ax,0002h
int 	33h
ret
MousePointerOff ENDP


PUBLIC MouseGetXCoord
MouseGetXCoord PROC
mov 	ax,0003h
int 	33h
mov	ax, dx
ret
MouseGetXCoord ENDP

PUBLIC MouseGetYCoord
MouseGetYCoord PROC
mov 	ax,0003h
int 	33h
mov	ax, cx
ret
MouseGetYCoord ENDP


PUBLIC MouseReadButtons
MouseReadButtons PROC
mov 	ax,0003h
int 	33h
mov	ax, bx
ret
MouseReadButtons ENDP


END
The PUBLIC is used to export the procedure, so it can be used in QB (or other languages). The '.MODEL MEDIUM' refers to medium memory model, and I'm still not exactly sure what this means (anyone know?), I just know it works :). The rest of it should be fairly obvious. The next step is to assemble the code. Assuming the tasm\bin directory is on your path, and you called the source file qbmouse.qsm, just type:
tasm qbmouse
If all goes well, you should now have a file called qbmouse.obj, so onto the next stage.

2)Creating the QuickBasic Library

This stage is really quite simple. First, make sure the qb directory is on your path, and type:
c:\qbmouse>link /qu qbmouse
Run File [QBMOUSE.QLB]:  (push enter) 
List File [NUL.MAP]:     (push enter) 
Libraries [.LIB]: C:\QB\BQLB45.LIB
c:\qbmouse>
(obviously i have assumed your qb directory is c:\qb) You should now have the file 'qbmouse.qlb'. Copy this file into your qbasic directory. Now, onto the final stage.

3)Writing the qb code

In order to use the new library file, you have to load qb with the /l switch:
c:\qb>qb /l qbmouse.qlb 
Once in QB, the new procedures need to be declared:
DECLARE SUB MousePointerOn
DECLARE SUB MousePointerOff
DECLARE FUNCTION MouseGetXCoord%
DECLARE FUNCTION MouseGetYCoord%
DECLARE FUNCTION MouseReadButtons%
The '%' following the functions indicates that the function returns an integer value. If you know much BASIC, then the rest should be fairly easy (if not, why are you reading this?). The qbasic program below will test switching the mouse pointer on and off, then display the co-ordinates of the mouse, and if any of the buttons have been pushed; exit though ctrl-break :)
DECLARE SUB MousePointerOn
DECLARE SUB MousePointerOff
DECLARE FUNCTION MouseGetXCoord%
DECLARE FUNCTION MouseGetYCoord%
DECLARE FUNCTION MouseReadButtons%

CLS
SCREEN 0
PRINT "Press space to turn pointer on."
SLEEP
MousePointerOn

PRINT "Press space to turn pointer off."
SLEEP
MousePointerOff


PRINT "and press space to turn pointer back on."
SLEEP
MousePointerOn
MousePointerOn

CLS


10 LOCATE 1, 1
PRINT MouseGetXCoord, MouseGetYCoord
LOCATE 10, 1
IF MouseReadButtons = 1 THEN PRINT "Button1" ELSE PRINT "       "
LOCATE 20, 1
IF MouseReadButtons = 2 THEN PRINT "Button2" ELSE PRINT "       "
20 GOTO 10
Changeing the screen mode to something like 12 will show a nice graphical mouse pointer, not a block like in screen 0.
You can download the asm and qbasic sources files, along with the complied QuickBasic library by clicking HERE (4k)
Well, thats it for now. If you have *any* questions, comments (good/bad) then please email me at Anonymous101@Uncreativelabs.net or (preferabley) PM me through the Uncreative Labs fourm.
At some point in the future, I hope to add other pages on a similar topic (although hopefully a bit more advanced), so I would be grateful for any feedback/suggestions.

BACK



Uncreative Labs Main Page    Contact Us    PC/XT & AT Forum